#pragma once

#include <iostream>
#include <string>
#include <pthread.h>

typedef void (*fun_c)(void *); // 函数指针

class Thread
{
    // 线程的状态
    typedef enum
    {
        EXIST // 存在
        ,
        RUNNING // 运行中
        ,
        STOP // 已终止
    } ThreadStatus;

public:
    Thread(int num = 0, fun_c fun = nullptr, void *arg = nullptr)
        : _id(0), _fun(fun), _arg(arg), _status(EXIST)
    {
        char name[64];
        snprintf(name, sizeof name, "thread-%d", num);
        _name = name;
    }

    Thread(const Thread &td)
    {
        _id = td._id;
        _name = td._name;
        _fun = td._fun;
        _arg = td._arg;
        _status = td._status;
    }

    Thread &operator=(Thread tmp)
    {
        swap(tmp);
        return *this;
    }

    void swap(Thread &td)
    {
        _id = td._id;
        _name = td._name;
        _fun = td._fun;
        _arg = td._arg;
        _status = td._status;
    }

    ~Thread() {}

    std::string getName() // 获取线程的名字
    {
        return _name;
    }

    std::string getID() // 获取线程的ID
    {
        if (_status == EXIST)
        {
            std::cerr << "线程还没有创建" << std::endl;
            return std::string();
        }

        // 转十六进制显示
        char idStr[64];
        snprintf(idStr, sizeof idStr, "%x", _id);

        return "0x" + std::string(idStr);
    }

    ThreadStatus getStatus() // 获取进程的状态
    {
        if (_status == EXIST)
            std::cerr << "线程还没有创建" << std::endl;

        return _status;
    }

    static void *runHelper(void *arg)
    {
        // 此时为静态函数，需要使用 this 指针（arg）
        Thread *pt = static_cast<Thread *>(arg);

        pt->_fun(pt->_arg); // 尝试直接调用回调函数

        //(*pt)();

        return nullptr;
    }

    void operator()()
    {
        if (_fun != nullptr)
            _fun(_arg);
    }

    void run() // 运行线程中对应的函数
    {
        // 通过回调函数 _fun 完成对 create 函数的调用
        int ret = pthread_create(&_id, nullptr, runHelper, this);
        if (ret != 0)
        {
            std::cerr << "线程创建失败" << std::endl;
            exit(1);
        }
        _status = RUNNING;
    }

    void join() // 等待线程的运行结束
    {
        int ret = pthread_join(_id, nullptr);
        if (ret != 0)
        {
            std::cerr << "等待线程失败" << std::endl;
            return;
        }

        _status = STOP;
    }

    void detach() // 线程分离
    {
        pthread_detach(_id);
    }

private:
    pthread_t _id; // 线程的 id
    std::string _name;
    fun_c _fun;           // 待回调的函数指针
    void *_arg;           // 传入的参数4
    ThreadStatus _status; // 线程的状态
};